﻿#include "wsignallampnode.h"
#include "wnodemanager.h"
#include "wxpolygonex.h"
#include "../common.h"
#include "../scriptmanager.h"
#include "../cmainframe.h"
#include <wx/strconv.h>

WSignalLampNode::WSignalLampNode()
    : m_NameAlignment(TextAlignment::LEFT),
      m_SLRouteType(SLRouteType::ROUTE_NULL)
{
    this->setNodeType(NODE_SIGNAL);
}

WSignalLampNode::WSignalLampNode(wxString pname)
    : WBaseNode(pname),
      m_NameAlignment(TextAlignment::LEFT),
      m_SLRouteType(SLRouteType::ROUTE_NULL)
{
    this->setNodeType(NODE_SIGNAL);

    /// 注册结点到lua中
    ScriptManager::getSingleton().registerBaseNodetoLua("L_",this);

    m_onMouseEventString = wxString(wxT("onMouseEvent_L_")+this->getName());
    m_onUpdateEventString = wxString(wxT("update_L_")+this->getName());
    m_onDrawEventString = wxString(wxT("draw_L_")+this->getName());
}

WSignalLampNode::~WSignalLampNode()
{

}

/// 建立脚本文件
bool WSignalLampNode::createScriptFile(void)
{
    // 目标文件
    const wxString decScriptFile = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+
                             wxString::Format("/resources/scripts/nodes/%s.lua",this->getName());

    if(wxFileExists(decScriptFile))
        return false;

    const wxString decScriptDir = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+
            "/resources/scripts/nodes";

    // 检测指定目录是否存在，不存在创建目录
    if(!wxDir::Exists(decScriptDir))
    {
        if (!wxFileName::Mkdir(decScriptDir, 0755, wxPATH_MKDIR_FULL))
            return false;
    }

    wxString tmpScriptContent = wxString(wxT("%s_radius = 1.0;\n"
                                         "\n"
                                         "--结点更新\n"
                                         "function update_%s()\n"
                                         "\n"
                                         "end\n"
                                         "\n"
                                         "--[[鼠标事件处理]]--\n"
                                         "function onMouseEvent_%s(event)\n"
                                         "  local p%s = WSignalLampNode.castFromBase(%s);\n"
                                         "  if p%s == nil then return end\n"
                                         "\n"
                                         "  if p%s:getBoundingRect():containsPoint(event:GetPosition()) then\n"
                                         "      -- 左键按下，信号灯必须在正常状态才能选中信号灯\n"
                                         "      if event:ButtonDown(1) == true and p%s:getOperState() == 2 then\n"
                                         "          p%s:setOperState(0);\n"
                                         "      end\n"
                                         "\n"
                                         "      %s_radius = 1.2;\n"
                                         "  else\n"
                                         "      -- 右键抬起，取消选中信号灯\n"
                                         "      if event:ButtonDown(3) == true and p%s:getOperState() == 0 then\n"
                                         "          p%s:setOperState(2);\n"
                                         "      end\n"
                                         "\n"
                                         "      %s_radius = 1.0;\n"
                                         "  end\n"
                                         "end\n"
                                         "\n"
                                         "--绘制结点\n"
                                         "function draw_%s(painter)\n"
                                         "   local p%s = WSignalLampNode.castFromBase(%s);\n"
                                         "   if p%s == nil then return end\n"
                                         "\n"
                                         "   local tmpPos = p%s:getScreenPosition();\n"
                                         "   painter:DrawCircle(tmpPos,10,17,\n"
                                         "                  %s:getColourByState(),\n"
                                         "                  wxColour(255,255,255,255),\n"
                                         "                  3.0,\n"
                                         "                  %s_radius);\n"
                                         "\n"
                                         "   --绘制结点名称\n"
                                         "   p%s:drawName(painter);\n"
                                         "end"));
    tmpScriptContent.Replace("%s","L_"+this->getName());


    wxFile decfile;
    if (!decfile.Create(decScriptFile, true))
        return false;

    wxCSConv conv("UTF-8");

    if (!decfile.Write(tmpScriptContent,conv)) {
        decfile.Close();
        return false;
    }

    decfile.Close();

    return true;
}

/// 根据状态得到颜色
wxColour WSignalLampNode::getColourByState(void)
{
    const NodeSignalState state = (NodeSignalState)this->getSignalState();
    const NodeType type = (NodeType)this->getNodeType();

    if (state == NodeSignalState::OCCUPY) {
        if (type == NodeType::NODE_SWITCH) {
            return wxColour(255, 0, 0, 255); // Red for occupied switch
        }
        return wxColour(255, 255, 255, 255); // White otherwise
    }
    else if (state == NodeSignalState::CLEAR) {
        if (type == NodeType::NODE_SIGNAL) {
            return wxColour(0, 0, 255, 255); // Blue for clear signal
        }
        return wxColour(255, 255, 255, 255); // White otherwise
    }
    else if (state == NodeSignalState::NOSIGNAL) {
        if (type == NodeType::NODE_SWITCH) {
            return wxColour(255, 255, 0, 255); // Yellow for no-signal switch
        }
        return wxColour(0, 0, 255, 255); // Blue for no-signal signal (same as CLEAR)
    }

    return wxColour(255, 255, 255, 255); // Default white
}

/// 工作区域改变
void WSignalLampNode::changeWorkingRect(wxRect workingrect)
{
    WBaseNode::changeWorkingRect(workingrect);

    std::map<wxString,tagMountPoint> mountpoints = this->getAllMountPoints();
    if(mountpoints.empty())
    {
        // 计算实际显示点
        mScreenCenterPosition = wxRealPoint(workingrect.GetLeftTop().x+workingrect.GetWidth()*(mCenterPosition.x/100.0f),
                                  workingrect.GetLeftTop().y+workingrect.GetHeight()*(mCenterPosition.y/100.0f));
    }
    else
    {
        // 计算实际显示点
        mScreenCenterPosition = wxRealPoint(workingrect.GetLeftTop().x+workingrect.GetWidth()*((*mountpoints.begin()).second.pos.x/100.0f)+mCenterPosition.x,
                                            workingrect.GetLeftTop().y+workingrect.GetHeight()*((*mountpoints.begin()).second.pos.y/100.0f)+mCenterPosition.y);
    }

    // 计算包围盒
    wxPoint points[4];
    points[0] = wxPoint(mScreenCenterPosition.x-IDD_SIGNALLAMP_RADIUS,mScreenCenterPosition.y-IDD_SIGNALLAMP_RADIUS);
    points[1] = wxPoint(mScreenCenterPosition.x+IDD_SIGNALLAMP_RADIUS,mScreenCenterPosition.y-IDD_SIGNALLAMP_RADIUS);
    points[2] = wxPoint(mScreenCenterPosition.x+IDD_SIGNALLAMP_RADIUS,mScreenCenterPosition.y+IDD_SIGNALLAMP_RADIUS);
    points[3] = wxPoint(mScreenCenterPosition.x-IDD_SIGNALLAMP_RADIUS,mScreenCenterPosition.y+IDD_SIGNALLAMP_RADIUS);

    this->setBoundingRect(wxPolygonEx(4,points));
}

/// 处理鼠标事件
bool WSignalLampNode::OnMMouseEvent(wxMouseEvent event)
{
    if(m_onMouseEventString == "")
        return false;

    /// 调用结点的鼠标事件接口
    ScriptManager::getSingleton().callLuaFunctionWithBaseNodeMouseEvent(m_onMouseEventString.ToUTF8().data(),
                                                                        event);

    return false;
}

/// 更新
void WSignalLampNode::update(void)
{
    if(m_onUpdateEventString == "")
        return;

    // 调用lua更新脚本接口
    ScriptManager::getSingleton().callLuaFunctionWithBaseNodeUpdate(m_onUpdateEventString.ToUTF8().data());
}

/// 绘制标题
void WSignalLampNode::drawName(maindrawscene *painter)
{
    if(this->getName() == "" || painter == NULL)
        return;

    float decAngle = 0.0f;

    wxVector<tagMountPoint> pMountPoints = this->getMountPointByDir((int)m_NameAlignment);

    if(pMountPoints.size() == 1)
    {
        decAngle = pMountPoints[0].angle;

        if(decAngle <= 180.0f)
            decAngle = -(decAngle - 180.0f);
        else
            decAngle = 360.0f - (decAngle - 180.0f);
    }

    painter->DrawText3(this->getName().ToUTF8().data(),
                       this->getScreenPosition(),
                       this->getTextColourByState(),
                       decAngle,
                       (int)m_NameAlignment,
                       15.0f);
}

/// 绘制
void WSignalLampNode::draw(maindrawscene *painter)
{
    // 绘制包围盒
    //this->DrawBoundingBox(painter);

    if(m_onDrawEventString != "")
    {
        // 调用lua绘制脚本接口
        ScriptManager::getSingleton().callLuaFunctionWithBaseNodeDraw(painter,m_onDrawEventString.ToUTF8().data());
    }

    // 绘制挂载点
    this->DrawMountPoints(painter);
}
